﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.OMM.ConnectionManager.MSMQ;
using Sinacor.OMM.HealthMonitor.Entity;
using Sinacor.OMM.HealthMonitor.Collector;
using System.Messaging;
using Sinacor.OMM.HealthMonitor.Entity.Common;
using Sinacor.OMM.HealthMonitor.Entity.Receiver;
using Sinacor.OMM.HealthMonitor.Entity.Router;
using Sinacor.OMM.HealthMonitor.Entity.HftProcessor;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Sinacor.OMM.HealthMonitor.Server.TcpServer;
using System.Threading;
using Sinacor.OMM.HealthMonitor.Collector.SharedHealthDataMemoryStorage.Receiver;
using Sinacor.OMM.HealthMonitor.Collector.SharedHealthDataMemoryStorage.Router;
using Sinacor.OMM.HealthMonitor.Collector.SharedHealthDataMemoryStorage.HftProcessor;
using Sinacor.OMM.HealthMonitor.Collector.SharedHealthDataMemoryStorage.Dumper;
using Sinacor.OMM.HealthMonitor.Client;
using Sinacor.OMM.HealthMonitor.Server.Controller;
using Sinacor.OMM.HealthMonitor.Configuration;
using Sinacor.OMM.Util;

namespace Sinacor.OMM.HealthMonitor.Server
{
    public class HealthMonitorMain : IDisposable
    {

        private const string TRACE_FOLDER_NAME = "Monitor Sistema";

        MsmqReceiver _msmqReceiver;
        HealthMonitorTcpServer _healthMonitorTcpServer;
        HealthStatusController _healthStatusController;

        TraceWriter _traceWriter;

        private bool _keepRunning = false;

        public HealthMonitorMain()
        {
        }

        public void Run()
        {
            _healthStatusController = new HealthStatusController();
            _healthStatusController.OnHealthStatusUpdate += new HealthStatusController.HealthStatusUpdateHandler(healthStatusController_OnHealthStatusUpdate);

            _traceWriter = Tracer.GetInstance(TRACE_FOLDER_NAME, "Serviço de Monitoração.log");

            IniciaServidorTcp();
            InicializaRecepcaoHealthMessagesByMsmq();
        }

        private void IniciaServidorTcp()
        {
            _healthMonitorTcpServer = new HealthMonitorTcpServer();

            Thread thr = new Thread(new ThreadStart(_healthMonitorTcpServer.Run));
            thr.Start();

            _traceWriter.Trace("Disparou o Start do Servidor Tcp...");
        }

        private void InicializaRecepcaoHealthMessagesByMsmq()
        {
            _msmqReceiver = new MSMQHelper().CreateRepositoryMsmqReceiver(OMM.HealthMonitor.Configuration.HealthMonitorConfigurationManager.HealthMonitorConfiguration.MSMQHealthMonitorQueue);
            _msmqReceiver.MessageReceived += new MsmqReceiver.MessageArrival(_msmqReceiver_MessageReceived);
            _traceWriter.Trace("Disparou o Start do Receptor MSMQ...");
        }

        void _msmqReceiver_MessageReceived(Message msg, PSE.Framework.Messaging.MessageReceivedEventArgs e)
        {            
            try
            {
                _healthStatusController.UpdateMemorySnapshot(msg);
                e.Result = true;
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro OnHealthMessageArrival... [" + ex.Message);
                _traceWriter.Trace("OnHealthMessageArrival: [" + ex.StackTrace);
                e.Result = false;
            } 
        }

        private bool IsRunning()
        {
            return _keepRunning;
        }

        private void healthStatusController_OnHealthStatusUpdate(byte[] healthStatusMemorySnapshotSerialized)
        {
            try
            {
                if (_healthMonitorTcpServer != null)
                    _healthMonitorTcpServer.SendBroadCast(healthStatusMemorySnapshotSerialized);
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro OnHealthStatusUpdate..." + ex.Message);
                _traceWriter.Trace("OnHealthStatusUpdate: [" + ex.StackTrace);
            }
        }

        public bool OnHealthMessageArrival(Message healthMsg)
        {
            bool ret = false;

            try
            {
                _healthStatusController.UpdateMemorySnapshot(healthMsg);
                ret = true;
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro OnHealthMessageArrival... [" + ex.Message);
                _traceWriter.Trace("OnHealthMessageArrival: [" + ex.StackTrace);
                ret = false;
            }

            return ret;
        }

        #region IDisposable Members

        public void Dispose()
        {
            _keepRunning = false;
            try
            {
                if (_msmqReceiver != null)
                    _msmqReceiver.Dispose();
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro Disposing MsmqReceiver...");
                _traceWriter.Trace("Dispose: [" + ex.StackTrace);
            }

            try
            {
                if(_healthStatusController != null)
                    _healthStatusController.Dispose();
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro Disposing HealthStatusController...");
                _traceWriter.Trace("Dispose: [" + ex.StackTrace);
            }

            try
            {
                if (_healthMonitorTcpServer != null)
                    _healthMonitorTcpServer.Dispose();
            }
            catch (Exception ex)
            {
                _traceWriter.Trace("Erro Disposing TcpSever...");
                _traceWriter.Trace("Dispose: [" + ex.StackTrace);
            }

            Tracer.Destroy();
        }

        #endregion
    }
}
